//------------------------------------------------------------------------------
//!	@file dsp_m2s.c
//!	@brief
//!		DSP mono to stereo file
//!
//!	@Description
//!		This DSP effect file shall support numerous DSP experiments without
//!		recoding the effect over and over.
//!
//!	$Id: dsp_m2s.c 163 2013-03-03 07:18:56Z ac.verbeck@gmail.com $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	Copyright and Disclaimer Notice
//
//	Copyright (c) 2013 A.C. Verbeck
//
//	This file is part of DSP lab: an experimenters library
//
//	DSP lab is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	DSP lab is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with DSP lab.  If not, see <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <stdint.h>
#include <stdbool.h>

#include <sndfile.h>

#include "dsp.h"

//------------------------------------------------------------------------------
// Local data
//------------------------------------------------------------------------------
static SF_INFO	i_sf,o_sf;
static double	param_d[DBL_PARAM_CT];
static double	atten_dB = 0.0;

//------------------------------------------------------------------------------
//!	@brief
//!		parameter init / processing / end functions
//!
//!	@Description
//!		These functions are called as follows:
//!		dsp_param_init:		is called at the start of DSP processing
//!		dsp_param_process:	is called after each audio buffer is processed
//!		dsp_param_end:		is called at the end of DSP processing
//!
//!	@param
//!		none
//!
//!	@return
//!		none
//------------------------------------------------------------------------------
void dsp_param_init(double pdp[])
{
	for (int i=0; i<DBL_PARAM_CT; i++)		param_d[i] = pdp[i];				//	Copy all four parameters to a local array
	atten_dB = pow(10.0, param_d[0]/20.0);										//	Calculate attenuation
}

void dsp_param_process(void)
{
}

void dsp_param_end(void)
{
}

//------------------------------------------------------------------------------
//!	@brief
//!		dsp buffer init function
//!
//!	@param
//!		SF_INFO* sfinfo: Pointer to a sound-file information structure
//!
//!	@return
//!		none
//------------------------------------------------------------------------------

void dsp_buff_init(SF_INFO* i_sfinfo, SF_INFO* o_sfinfo)
{
	i_sf = *i_sfinfo;															//	Save input sound file info
	o_sf = *o_sfinfo;															//	Save output sound file info

	if (i_sf.channels != 1) {													//	How many channels does this effect support
		printf("This DSP effect can only process mono input files\n");
		exit(0);
	}
	if ((i_sf.format & SF_FORMAT_SUBMASK) != SF_FORMAT_FLOAT) {					//	Data format
		printf("This DSP effect can only process 32-bit floating point files\n");
		exit(0);
	}
	if ((i_sf.format & SF_FORMAT_ENDMASK) != SF_ENDIAN_FILE) {					//	Endian file types
		printf("This DSP effect can only process native endian files\n");
		exit(0);
	}
}

//------------------------------------------------------------------------------
//!	@brief
//!		dsp buffer processing function
//!
//!	@param
//!		double*		b_out:	Buffer to place the modified data
//!		double*		b_in:	Incoming audio data buffer
//!		sf_count_t	ct:		Number of items to process in this function
//!
//!	@return
//!		none
//------------------------------------------------------------------------------
void dsp_buff_process(double* b_out, double* b_in, sf_count_t ct)
{
	double l_val, r_val;

	for (sf_count_t i=0; i<ct; i++)	{											//	Loop through the input buffer
		r_val = l_val = *b_in++;												//	Set left and right to the same value

		*b_out++ = l_val * atten_dB;											//	Left output value equals the input value multiplied by the current attenuation
		*b_out++ = r_val * atten_dB;											//	Right output value equals the input value multiplied by the current attenuation
	}
}

void dsp_buff_end(void)
{
}

//
//	End: dsp_m2s.c
//